-
Couldn't load subscription status.
- Fork 71
Use .subset() to avoid hackily calling into Extract_subset()
#2087
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can delete all of this hackery now!
| r_obj* alt_subscript = KEEP(vec_subscript_materialize(subscript)); \ | ||
| r_obj* out = ALTVEC_EXTRACT_SUBSET_PROXY(x, alt_subscript, r_null); \ | ||
| FREE(1); \ | ||
| if (out != NULL) { \ | ||
| return out; \ | ||
| } \ | ||
| } \ | ||
| if (is_compact_rep(subscript)) { \ | ||
| return vec_slice_altrep(x, subscript); \ | ||
| } else if (is_compact_rep(subscript)) { \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note can no longer fall through to vctrs slicing code on ALTREP objects
| #define SLICE_BARRIER(RTYPE, CONST_DEREF, SET, NA_VALUE) \ | ||
| if (is_compact_rep(subscript)) { \ | ||
| if (!materialize && ALTREP(x)) { \ | ||
| return vec_slice_altrep(x, subscript); \ | ||
| } else if (is_compact_rep(subscript)) { \ | ||
| SLICE_BARRIER_COMPACT_REP(RTYPE, CONST_DEREF, SET, NA_VALUE); \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notably we weren't actually doing anything with ALTREP in the barrier path for characters and lists
But all our tests are for a character ALTREP vector, so they weren't actually hitting this at all and it was materializing the test vector.
I've added extra checks to our tests that confirm that after the vec_slice(x) call that x is still not materialized, which previously would have failed.
Base R also now has support for ALTREP lists thanks to Gabor, so those would now be supported by this as well.
| test_that("vec_slice() works with Altrep classes with custom extract methods", { | ||
| x <- .Call(vctrs_altrep_rle_Make, c(foo = 10L, bar = 5L)) | ||
| x <- chr_rle(foo = 10L, bar = 5L) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note this only tests the barrier altrep path (character / list). We don't have an altrep test class for the non-barrier path (like an altrep integer rep or something).
We could make one if we feel like we need the coverage
Part of #1933
In #696 we introduced some admittedly hacky machinery that mimicked R's internal ALTREP methods table to get access to an ALTREP class's
Extract_subsetmethod so we could call it directly fromvec_slice(), avoiding ALTREP materialization.That used
STDVEC_DATAPTR(), a non-API function.DATAPTR()is also non-API, thoughDATAPTR_RO()seems to be allowed. In theory maybe we could just swap forDATAPTR_RO(), but I wanted to take a look at this because this feels like fairly brittle code that R Core probably would not like us doing.Rather than trying to call the ALTREP
Extract_subsetmethod directly, I took a look at the code paths in R itself that end up calling this. Both[and.subset()get you there. I'd like to avoid calling[to avoid any S3 method funny business, as I don't want to end up in an endless loop calling intovctrs::vec_slice(), but.subset()seems very useful for this.This PR switches us to always go through
.subset()for ALTREP objects invec_slice().A notable difference is that previously if there was no
Extract_subsetmethod, then we could fall back to vctrs slicing code. Now it falls back to base R slicing code, which uses theEltmethod repeatedly. I do not think there is any safe/approved way to keep the previous behavior.Here is the example from #696 (comment) reproduced with this PR
Created on 2025-10-24 with reprex v2.1.1